/*
 * @Author: wushengran
 * @Date: 2024-06-04 13:58:28
 * @Description: 
 * 
 * Copyright (c) 2024 by atguigu, All Rights Reserved. 
 */
#include "tim1.h"

#define MODE_INPUT                        0
#define MODE_OUTPUT_SPEED_10MHZ           1
#define MODE_OUTPUT_SPEED_2MHZ            2
#define MODE_OUTPUT_SPEED_50MHZ           3

#define CONF_OUTPUT_GENERAL_PUSH_PULL     0
#define CONF_OUTPUT_GENERAL_OPEN_DRAIN    1
#define CONF_OUTPUT_ALTERNATE_PUSH_PULL   2
#define CONF_OUTPUT_ALTERNATE_OPEN_DRAIN  3

#define CONF_INPUT_ANALOG                 0
#define CONF_INPUT_FLOATING               1
#define CONF_INPUT_PULL_UP_DOWN           2
#define CONF_INPUT_RESERVED               3

void TIM1_Init(void)
{
    // 1. 开启时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;

    // 2. GPIO工作模式，PA8：输入 CNF-10，MODE-11
    GPIOA->CRH &= ~(0xF << (0 * 4));
    GPIOA->CRH |= MODE_OUTPUT_SPEED_50MHZ         << (0 * 4);
    GPIOA->CRH |= CONF_OUTPUT_ALTERNATE_PUSH_PULL << (0 * 4 + 2);

    // 3. 定时器配置
    
    // 3. 时基部分
    // 3.1 预分频值 7199，得到 10000 Hz
    TIM1->PSC = 7199;

    // 3.2 重装载值，4999，每隔 0.5s 溢出一次
    TIM1->ARR = 4999;

    // 3.3 计数方向
    TIM1->CR1 &= ~TIM_CR1_DIR;

    // 3.4 重复计数
    TIM1->RCR = 4;

    // 4. 输出通道部分
    
    // 4.1 配置通道1为输出模式
    TIM1->CCMR1 &= ~TIM_CCMR1_CC1S;
    
    // 4.2 配置通道1为 PWM1 模式， OC1M - 100
    TIM1->CCMR1 |= TIM_CCMR1_OC1M_2;
    TIM1->CCMR1 |= TIM_CCMR1_OC1M_1;
    TIM1->CCMR1 &= ~TIM_CCMR1_OC1M_0;

    // 4.3 配置CCR1寄存器，占空比设置为50%即可
    TIM1->CCR1 = 2500;

    // 4.4 配置极性
    TIM1->CCER &= ~TIM_CCER_CC1P;

    // 4.5 产生一个更新事件，刷新寄存器的值
    TIM1->CR1 |= TIM_CR1_URS;
    TIM1->EGR |= TIM_EGR_UG;

    // 4.6 通道1使能
    TIM1->CCER |= TIM_CCER_CC1E;

    // 4.7 主输出使能
    TIM1->BDTR |= TIM_BDTR_MOE;

    // 5. 中断功能
    // 5.1 更新中断使能
    TIM1->DIER |= TIM_DIER_UIE;

    // 5.2 NVIC配置
    NVIC_SetPriorityGrouping(3);
    NVIC_SetPriority(TIM1_UP_IRQn, 3);
    NVIC_EnableIRQ(TIM1_UP_IRQn);

}

// 将定时器的开关包装成函数
void TIM1_Start(void)
{
    TIM1->CR1 |= TIM_CR1_CEN;
}

void TIM1_Stop(void)
{
    TIM1->CR1 &= ~TIM_CR1_CEN;
}

// 中断服务程序
void TIM1_UP_IRQHandler(void)
{
    // 清除中断标志位
    TIM1->SR &= ~TIM_SR_UIF;

    // 停掉定时器
    TIM1_Stop();
}






